%{

#include <iostream>

typedef void* Expression;
typedef void* Literal;
typedef void* Statement;
typedef void* CallIndex;
typedef void* Variable;

#include "main.hpp"

extern void yyerror( const char* errorString );
extern int yylineno;

%}

whitespace    [ \t]+
delimiter     [\[\]\(\);:,]
digit         [0-9]
letter        [a-zA-Z]
assignop      ":="
exprop       "*"|"+"|"|"
relop         "="|"<"|">"
integer       {digit}+
identifier    {letter}({letter}|{digit})*
character     "'"."'"
boolean       "true"|"false"

%x IN_COMMENT

%%

\n                          { yylineno++; }

"program"                   return PROGRAM;

"begin"                     return BEG;
"end"                       return END;

"type"                      return ARRAY;
"integer"|"boolean"|"char"  { yylval.type = new std::string( yytext ); return TYPE; }
"value"                     return VALUE;

"procedure"                 return PROCEDURE;

"if"                        return IF;
"then"                      return THEN;
"else"                      return ELSE;
"endif"                     return ENDIF;

"while"                     return WHILE;
"do"                        return DO;
"endwhile"                  return ENDWHILE;

"read"                      return READ;
"write"                     return WRITE;

"not"                       return NOT;

{whitespace}                ;

{delimiter}                 return *yytext;

{assignop}                  return ASSIGNOP;

{exprop}                    return *yytext;
{relop}                     { yylval.character = *yytext; return RELOP; }

{integer}                   { yylval.integer   = atoi(yytext);           return INT_LITERAL; }
{character}                 { yylval.character = yytext[1];              return CHAR_LITERAL; }
{boolean}                   { yylval.boolean   = !strcmp(yytext,"true"); return BOOL_LITERAL; }

{identifier}                { yylval.identifier = new std::string( yytext ); return IDENTIFIER; }

.                           yyerror( "Invalid character." );

"/*"                        BEGIN(IN_COMMENT);

<IN_COMMENT>
{
     "*/"      BEGIN(INITIAL);
     [^*\n]+   ; // ignore everything inside the comments
     "*"       ; // ignore the lone star
     \n        yylineno++;
}


%%

void yyerror( const char* str )
{
  printf( "%s : %d\n", str, yylineno );
}

int yywrap()
{
  return 1;
}
